//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package common;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import common.SocksProxy.state;
import exceptions.AccountStopAndReconnectException;
import exceptions.AccountStopException;
import exceptions.RestartMainLoopException;
import messages.Base;
import messages.EndClientTurn;
import messages.EndClientTurnOK;
import messages.GetMessageTimeOut;
import messages.GoCity;
import messages.GoFishing;
import messages.GoHome;
import messages.GoVisitedGreg;
import messages.GoVisitedHome;
import messages.InitSecureConnection;
import messages.InitSecureConnectionOk;
import messages.Login;
import messages.LoginFailed;
import messages.LoginOK;
import messages.OutOfSync;
import messages.OwnCityData;
import messages.OwnFishingData;
import messages.OwnHomeData;
import messages.ServerDisconnected;
import messages.TCPChannelError;
import messages.TCPChannelNotConnected;
import messages.Unknown;
import messages.VisitedGregData;
import messages.VisitedHomeData;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class AccountProcess implements Runnable {
    final long msgsBreakTime = 10000L;
    final long mills = 10000L;
    private Thread thr;
    private Messaging msgProcess;
    private boolean disableReconnect;
    private String profileName;
    private SocksProxy socks;
    private int timeout;
    private Timer delayTimer;
    private Login profile;
    private final GlobalTimerIdentifier timerUnit = new GlobalTimerIdentifier();
    private Long AccountID;
    private Long HomeID;
    private LoginOK lOk;
    private IAccountProcess feedback;
    private boolean detaledLog = false;
    volatile boolean stopInProgress;
    volatile boolean doDisconnect;
    volatile boolean resetTickCounters;
    private final String LogDelailedPrefix = "AccountProcess.";

    public AccountProcess(String profileName, String AccountData, SocksProxy socks, IAccountProcess feedback) {
        this.init(profileName, new Login(StringUtils.stringToByteArray(AccountData)), socks, feedback);
    }

    public AccountProcess(String profileName, Login AccountData, SocksProxy socks, IAccountProcess feedback) {
        this.init(profileName, AccountData, socks, feedback);
    }

    private void init(String profileName, Login AccountData, SocksProxy socks, IAccountProcess feedback) {
        this.profileName = profileName;
        this.profile = AccountData;
        this.socks = socks;
        this.stopInProgress = false;
        this.doDisconnect = false;
        this.delayTimer = new Timer();
        this.lOk = null;
        this.feedback = feedback;
        this.AccountID = Long.valueOf(this.profile.AccountID.longValue());
    }

    public boolean getGetailedLog() {
        return this.detaledLog;
    }

    public void setDetailedLog(boolean action) {
        this.detaledLog = action;
    }

    public Long getAccountID() {
        return this.AccountID;
    }

    public Long getHomeID() {
        return this.HomeID;
    }

    public boolean isStarted() {
        return this.thr != null && this.thr.isAlive();
    }

    public synchronized void start() {
        if(!this.doDisconnect && !this.stopInProgress && !this.isStarted()) {
            String name = new String();
            if(this.profileName != null) {
                name = name + "." + this.profileName;
            }

            this.thr = new Thread(this, "profile" + name);
            this.thr.start();
        }

    }

    public void disconnect() {
        if(!this.doDisconnect) {
            this.doDisconnect = true;
            this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  External Stop Activity..."));
            this.stop();
            this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  External Stop Done."));
        }

    }

    private synchronized void stop() {
        if(!this.stopInProgress) {
            this.stopInProgress = true;
            this.delayTimer.cancel();
            Utils.threadJoin(this.thr);
            this.thr = null;
            if(this.msgProcess != null) {
                this.msgProcess.releaseAll();
            }

            this.doDisconnect = false;
            this.stopInProgress = false;
            if(this.feedback != null) {
                this.feedback.stoppedEvent(this.AccountID, this.HomeID);
            }
        }

    }

    public void run() {
        boolean doStopEntry = false;
        boolean tryReconnect = false;

        try {
            if(this.socks != null) {
                try {
                    this.socks.reconnect();

                    while(this.socks.getState() != state.relay && this.socks.getState() != state.relaySameAddr) {
                        try {
                            Thread.sleep(50L);
                        } catch (InterruptedException var22) {
                            ;
                        }

                        if(this.doDisconnect) {
                            this.socks.stop();
                            return;
                        }
                    }
                } catch (Exception var23) {
                    this.socks.stop();
                    return;
                }

                this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  SocksProxy relay started: game.haydaygame.com:9339"));
            }

            if(this.msgProcess == null) {
                this.msgProcess = new Messaging("game.haydaygame.com", "9339", this.profileName, this.profile.VersionNumber);
            } else if(this.socks != null) {
                this.msgProcess.updateServerAndPort("game.haydaygame.com", "9339");
            }

            Base ex;
            if(this.socks != null && this.socks.getState() == state.relaySameAddr) {
                this.msgProcess.updateTcpPort(this.socks.getTcpPort());
                this.msgProcess.resetToInitialState();
            } else {
                ex = this.msgProcess.reconnect();
                if(ex instanceof TCPChannelNotConnected) {
                    this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  Connect to server failed."));
                    return;
                }
            }

            HaydayNonce encoderNonce = null;
            String finger = null;
            Login lmsg = this.profile;
            this.msgProcess.putMessage(new InitSecureConnection(lmsg.ResourceFingerPrint));
            ex = this.msgProcess.getMessage();
            if(ex instanceof InitSecureConnectionOk) {
                InitSecureConnectionOk loggedIn = (InitSecureConnectionOk)ex;
                lmsg.sessionKey = loggedIn.sessionKey;
                encoderNonce = new HaydayNonce((byte[])null, (byte[])null, (byte[])null);
                lmsg.initialEncNonce = encoderNonce.get();
            } else {
                doStopEntry = true;
                if(ex instanceof LoginFailed) {
                    tryReconnect = false;
                    if(ex.isDecoded) {
                        LoginFailed loggedIn1 = (LoginFailed)ex;
                        ActionCode e = ActionCode.get(loggedIn1.ErrorCode);
                        switch(e.ordinal()) {
                            case 8:
                                this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  Connect:Try to get new account data!"));
                                tryReconnect = false;
                                break;
                            case 9:
                                JsonParser vhd = new JsonParser();
                                JsonObject jp = vhd.parse(loggedIn1.ResourceFingerprintData).getAsJsonObject();
                                finger = jp.getAsJsonPrimitive("sha").getAsString();
                                if(finger != null) {
                                    this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  New Resource Fingerprint: " + finger));
                                    lmsg.ResourceFingerPrint = finger;
                                    finger = null;
                                    lmsg.writeStream.resetOffset();
                                    this.profile = lmsg;
                                    String jo = StringUtils.bytesToString(lmsg.getContent());
                                    if(this.feedback != null) {
                                        this.feedback.updateLoginData(this.AccountID, this.HomeID, jo);
                                    }

                                    tryReconnect = true;
                                }
                                break;
                            case 10:
                            case 12:
                            default:
                                this.sysout(StringUtils.bytesToString(ex.readStream.getCopyOfByteArray()));
                                tryReconnect = false;
                                break;
                            case 11:
                                System.out.println(Logger.formatPT(this.profileName, "  Maintenance " + loggedIn1.MaintenanceTimeLeft + " seconds left."));
                                doStopEntry = true;
                                tryReconnect = true;
                                this.timeout = loggedIn1.MaintenanceTimeLeft.intValue() * 1000;
                            case 13:
                        }
                    }
                } else {
                    this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  Communication with server failed.\n"));
                }

                if(doStopEntry) {
                    return;
                }
            }

            lmsg.writeStream.resetOffset();
            this.msgProcess.setEncryptionNonce(new HaydayNonce((byte[])null, this.msgProcess.getClientKey(), Constants.ServerPublicKey));
            this.msgProcess.putMessage(lmsg);
            this.msgProcess.setEncryptionNonce(encoderNonce);
            ex = this.msgProcess.getMessage();
            boolean loggedIn2 = false;
            if(ex instanceof LoginOK) {
                this.lOk = (LoginOK)ex;
                loggedIn2 = true;
                this.HomeID = Long.valueOf(this.lOk.HomeID.longValue());
                if(lmsg.AccountID.longValue() == 0L) {
                    lmsg.AccountID = this.lOk.AccountID;
                    lmsg.PassToken = this.lOk.PassToken;
                    lmsg.writeStream.resetOffset();
                    this.profile = lmsg;
                    this.AccountID = Long.valueOf(lmsg.AccountID.longValue());
                    ByteStream e1 = new ByteStream(100);
                    lmsg.partialEncode(e1);
                    String vhd1 = StringUtils.bytesToString(e1.getCopyOfByteArray());
                    if(this.feedback != null) {
                        this.feedback.updateLoginData(this.AccountID, this.HomeID, vhd1);
                    }
                }
            } else {
                doStopEntry = true;
                if(ex instanceof LoginFailed) {
                    this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  Login failed:\n"));
                    tryReconnect = false;
                    if(ex.isDecoded) {
                        LoginFailed e2 = (LoginFailed)ex;
                        ActionCode vhd2 = ActionCode.get(e2.ErrorCode);
                        this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  Failed Reason: " + vhd2.getText()));
                        this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  " + e2.toString()));
                        switch(vhd2.ordinal()) {
                            case 8:
                                this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  Login: Try to get new account data!"));
                                tryReconnect = false;
                                break;
                            case 9:
                                JsonParser jp1 = new JsonParser();
                                JsonObject jo1 = jp1.parse(e2.ResourceFingerprintData).getAsJsonObject();
                                finger = jo1.getAsJsonPrimitive("sha").getAsString();
                                if(finger != null) {
                                    this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  New Resource Fingerprint: " + finger));
                                    lmsg.ResourceFingerPrint = finger;
                                    finger = null;
                                    lmsg.writeStream.resetOffset();
                                    this.msgProcess.putMessage(lmsg);
                                    ex = this.msgProcess.getMessage();
                                    if(ex instanceof LoginOK) {
                                        this.lOk = (LoginOK)ex;
                                        loggedIn2 = true;
                                        this.HomeID = Long.valueOf(this.lOk.HomeID.longValue());
                                        doStopEntry = false;
                                    } else {
                                        tryReconnect = false;
                                    }

                                    if(this.feedback != null) {
                                        lmsg.writeStream.resetOffset();
                                        String ld = StringUtils.bytesToString(lmsg.getContent());
                                        this.feedback.updateLoginData(this.AccountID, this.HomeID, ld);
                                    }
                                }
                                break;
                            case 10:
                            case 12:
                            default:
                                this.sysout(StringUtils.dumpBytes(ex.readStream.getCopyOfByteArray()));
                                tryReconnect = false;
                                break;
                            case 11:
                                System.out.println(Logger.formatPT(this.profileName, "  Maintenance " + e2.MaintenanceTimeLeft + " seconds left."));
                                doStopEntry = true;
                                tryReconnect = true;
                                this.timeout = e2.MaintenanceTimeLeft.intValue() * 1000;
                            case 13:
                        }
                    }
                } else {
                    this.sysout(Logger.formatP("AccountProcess." + this.profileName, "  Login response:\n" + ex.toString()));
                }

                if(doStopEntry) {
                    return;
                }
            }

            if(loggedIn2) {
                if(this.feedback == null) {
                    doStopEntry = true;
                    tryReconnect = false;
                    return;
                }

                Base e3 = this.feedback.loddegInEvent(this.AccountID, this.HomeID, this.lOk);
                this.timerUnit.reset();
                this.msgProcess.putMessage(e3);
                ex = this.waitForMsg(this.getResponseMsgName(e3), (Object)null);
                if(ex == null || ex instanceof GetMessageTimeOut || ex instanceof ServerDisconnected) {
                    return;
                }

                if(ex instanceof TCPChannelError) {
                    this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  Communication with server failed, idle time 15 seconds..."));
                    return;
                }

                if(ex instanceof OwnHomeData) {
                    OwnHomeData vhd3 = (OwnHomeData)ex;
                    if(this.feedback != null) {
                        this.feedback.ownHomeDataEvent(this.AccountID, this.HomeID, vhd3);
                    }

                    if(!vhd3.isDecoded) {
                        doStopEntry = true;
                        tryReconnect = false;
                        return;
                    }
                }

                if(ex instanceof OwnCityData) {
                    OwnCityData vhd4 = (OwnCityData)ex;
                    if(this.feedback != null) {
                        this.feedback.ownCityDataEvent(this.AccountID, this.HomeID, vhd4);
                    }

                    if(!vhd4.isDecoded) {
                        doStopEntry = true;
                        tryReconnect = false;
                        return;
                    }
                }

                if(ex instanceof OwnFishingData) {
                    OwnFishingData vhd5 = (OwnFishingData)ex;
                    if(this.feedback != null) {
                        this.feedback.ownFishingDataEvent(this.AccountID, this.HomeID, vhd5);
                    }

                    if(!vhd5.isDecoded) {
                        doStopEntry = true;
                        tryReconnect = false;
                        return;
                    }
                }

                if(ex instanceof VisitedHomeData) {
                    VisitedHomeData vhd6 = (VisitedHomeData)ex;
                    vhd6.setHomeId(this.HomeID.longValue());
                    vhd6.setAccountId(this.AccountID.longValue());
                    vhd6.decode(ex.readStream);
                    if(this.feedback != null) {
                        this.feedback.visitedHomeDataEvent(this.AccountID, this.HomeID, vhd6);
                    }

                    if(!vhd6.isDecoded) {
                        doStopEntry = true;
                        tryReconnect = false;
                        return;
                    }
                }
            }

            try {
                this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  Sync started..."));
                this.mainLoop();
                doStopEntry = true;
                tryReconnect = false;
            } catch (AccountStopAndReconnectException var20) {
                doStopEntry = true;
                tryReconnect = true;
                this.timeout = var20.getTimeout();
            } catch (AccountStopException var21) {
                doStopEntry = true;
                tryReconnect = false;
                this.timeout = 0;
            }

        } catch (Exception var24) {
            Utils.logException(var24, "AccountProcess." + this.profileName + ": Thread Exception: ");
        } finally {
            if(!this.doDisconnect) {
                this.doDisconnect = true;
                this.doFinalize(doStopEntry, tryReconnect, this.timeout);
            }

        }
    }

    public Integer getResponseMsgName(Base req) throws Exception {
        if(req instanceof GoHome) {
            return Integer.valueOf(24101);
        } else if(req instanceof GoCity) {
            return Integer.valueOf(24123);
        } else if(req instanceof GoFishing) {
            return Integer.valueOf(24122);
        } else if(req instanceof GoVisitedHome) {
            return Integer.valueOf(24102);
        } else if(req instanceof GoVisitedGreg) {
            return Integer.valueOf(24115);
        } else {
            throw new Exception("Invalid request message: " + req.getClass().getCanonicalName());
        }
    }

    public void whileNotDoDisconnect() throws AccountStopAndReconnectException, AccountStopException, RestartMainLoopException {
        while(!this.doDisconnect) {
            int prevTicks = this.timerUnit.getCurrentTicks();
            int ticks = this.timerUnit.getNextTick(10000L);
            Object feedbackData = null;
            EndClientTurn ectm = new EndClientTurn(Integer.valueOf(ticks));
            if(this.feedback != null) {
                feedbackData = this.feedback.tickActionEvent(this.AccountID, this.HomeID, ectm, prevTicks, ticks);
            }

            if(feedbackData instanceof AccountStopAndReconnectException) {
                throw (AccountStopAndReconnectException)feedbackData;
            }

            if(feedbackData instanceof AccountStopException) {
                throw (AccountStopException)feedbackData;
            }

            this.msgProcess.putMessage(ectm);
            if(this.feedback != null) {
                this.feedback.messageSentEvent(this.AccountID, this.HomeID, feedbackData);
            }

            Base msg = this.waitForMsg(Integer.valueOf(24112), ectm);
            if(msg instanceof OutOfSync) {
                throw new AccountStopAndReconnectException(msg, "OutOfSync detected, idle time 15 seconds...", 15000);
            }

            if(!(msg instanceof GetMessageTimeOut) && !(msg instanceof ServerDisconnected) && msg != null) {
                if(msg instanceof TCPChannelError) {
                    throw new AccountStopAndReconnectException(msg, "Communication with server failed, idle time 15 seconds...", 15000);
                }

                if(!this.waitForOneTickLeft(10000L)) {
                    continue;
                }

                throw new AccountStopException((Base)null, "Server disconnected.");
            }

            throw new AccountStopAndReconnectException(msg, "need to reconnect", 0);
        }

    }

    public void mainLoop() throws AccountStopAndReconnectException, AccountStopException {
        while(true) {
            try {
                EndClientTurn r = new EndClientTurn(Integer.valueOf(this.timerUnit.getCurrentTicks()));
                this.msgProcess.putMessage(r);
                Base msg = this.waitForMsg(Integer.valueOf(24112), r);
                if(!(msg instanceof GetMessageTimeOut) && !(msg instanceof ServerDisconnected) && msg != null) {
                    if(msg instanceof OutOfSync) {
                        throw new AccountStopAndReconnectException(msg, "OutOfSync detected, idle time 15 seconds...", 15000);
                    }

                    if(msg instanceof TCPChannelError) {
                        throw new AccountStopAndReconnectException(msg, "Communication with server failed, idle time 15 seconds...", 15000);
                    }

                    if(this.waitForOneTickLeft(10000L)) {
                        throw new AccountStopException((Base)null, "Server disconnected.");
                    }

                    this.whileNotDoDisconnect();
                    return;
                }

                throw new AccountStopAndReconnectException(msg, "need to reconnect", 0);
            } catch (RestartMainLoopException var3) {
                this.timerUnit.reset();
            }
        }
    }

    private void doFinalize(final boolean doStop, final boolean needReconnect, final int ftimeout) {
        Utils.asyncExec(new Runnable() {
            public void run() {
                boolean doReconnect = needReconnect;
                if(AccountProcess.this.disableReconnect) {
                    doReconnect = false;
                }

                if(doStop) {
                    AccountProcess.this.sysout(Logger.formatPT("AccountProcess." + AccountProcess.this.profileName, "  Stop Activity..."));
                    AccountProcess.this.stop();
                    AccountProcess.this.sysout(Logger.formatPT("AccountProcess." + AccountProcess.this.profileName, "  Stop Done."));
                }

                if(doReconnect) {
                    AccountProcess.this.sysout(Logger.formatPT("AccountProcess." + AccountProcess.this.profileName, "  Try to reconnect..."));
                    if(ftimeout > 0) {
                        AccountProcess.this.sysout(Logger.formatPT("AccountProcess." + AccountProcess.this.profileName, "  Reconnect will delayed for " + ftimeout / 1000 + " seconds \n"));
                        AccountProcess.this.setStartDelay(ftimeout);
                        AccountProcess.this.delayTimer.cancel();
                        AccountProcess.this.delayTimer = new Timer();
                        TimerTask tt = new TimerTask() {
                            public void run() {
                                AccountProcess.this.start();
                            }
                        };
                        AccountProcess.this.delayTimer.schedule(tt, (long)ftimeout);
                    } else {
                        AccountProcess.this.start();
                    }
                }

                AccountProcess.this.disableReconnect = false;
            }
        });
    }

    public void setStartDelay(int timeout) {
        this.timeout = timeout;
    }

    public int getStartDelay() {
        return this.timeout;
    }

    public Timer getTimer() {
        return this.delayTimer;
    }

    public void setTimer(Timer delayTimer) {
        this.delayTimer = delayTimer;
    }

    public void putMessage(Base msg) {
        if(this.msgProcess != null) {
            this.msgProcess.putMessage(msg);
        }

    }

    private Base waitForMsg(Integer wname, Object tmp) throws RestartMainLoopException {
        while(true) {
            Base msg = this.msgProcess.getMessage();
            if(msg == null || this.doDisconnect) {
                return null;
            }

            if(msg instanceof GetMessageTimeOut) {
                this.sysout(Logger.formatPT("AccountProcess." + this.profileName, " Error: " + msg));
                return msg;
            }

            if(msg instanceof ServerDisconnected) {
                return msg;
            }

            if(msg instanceof TCPChannelError) {
                return msg;
            }

            if(wname.intValue() == msg.getId()) {
                if(msg instanceof EndClientTurnOK) {
                    this.feedback.endClientTurnOkEvent(this.AccountID, this.HomeID, (EndClientTurnOK)msg);
                }

                return msg;
            }

            if(msg instanceof OutOfSync) {
                this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "  Out Of Sync: message process stopped!"));
                if(tmp != null && tmp instanceof EndClientTurn) {
                    this.sysout(Logger.formatPT("AccountProcess." + this.profileName, "\n  " + tmp.toString() + "\n"));
                }

                return msg;
            }

            this.messageFeedback(this.feedback, msg);
        }
    }

    private boolean waitForOneTickLeft(long mills) throws RestartMainLoopException {
        System.gc();
        long finalTime = (new Date()).getTime() + mills;

        while((new Date()).getTime() < finalTime) {
            try {
                long waiting = finalTime - (new Date()).getTime();
                if(waiting > 50L) {
                    waiting = 50L;
                }

                if(waiting > 0L) {
                    Thread.sleep(waiting);
                }

                while(this.msgProcess.hasReceivedMessages()) {
                    Base m = this.msgProcess.getMessage();
                    this.messageFeedback(this.feedback, m);
                    if(m instanceof ServerDisconnected) {
                        return true;
                    }
                }
            } catch (InterruptedException var8) {
                ;
            }

            if(this.doDisconnect) {
                break;
            }
        }

        return false;
    }

    public void messageFeedback(IAccountProcess fb, Base msg) throws RestartMainLoopException {
        if(fb != null) {
            if(msg instanceof Unknown) {
                fb.unknownMessageReceiveEvent(this.AccountID, this.HomeID, (Unknown)msg);
            } else {
                if(msg instanceof OwnHomeData) {
                    fb.ownHomeDataEvent(this.AccountID, this.HomeID, (OwnHomeData)msg);
                    throw new RestartMainLoopException();
                }

                if(msg instanceof OwnCityData) {
                    fb.ownCityDataEvent(this.AccountID, this.HomeID, (OwnCityData)msg);
                    throw new RestartMainLoopException();
                }

                if(msg instanceof OwnFishingData) {
                    fb.ownFishingDataEvent(this.AccountID, this.HomeID, (OwnFishingData)msg);
                    throw new RestartMainLoopException();
                }

                if(msg instanceof VisitedHomeData) {
                    VisitedHomeData vhd = (VisitedHomeData)msg;
                    vhd.setHomeId(this.HomeID.longValue());
                    vhd.setAccountId(this.AccountID.longValue());
                    vhd.decode(msg.readStream);
                    fb.visitedHomeDataEvent(this.AccountID, this.HomeID, vhd);
                    throw new RestartMainLoopException();
                }

                if(msg instanceof VisitedGregData) {
                    fb.messageReceiveEvent(this.AccountID, this.HomeID, msg);
                    throw new RestartMainLoopException();
                }

                if(msg instanceof EndClientTurnOK) {
                    fb.endClientTurnOkEvent(this.AccountID, this.HomeID, (EndClientTurnOK)msg);
                } else {
                    this.feedback.messageReceiveEvent(this.AccountID, this.HomeID, msg);
                }
            }
        }

    }

    public void sysout(String log) {
        if(this.detaledLog) {
            System.out.println(log);
        }

    }
}
